package com.sinosoft.ptas.system.aop;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.List;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;


/**
 * 服务切面
 * 针对服务中的增加和删除类方法调用之前的处理
 * @author leichao
 */
@Component
@Aspect 
public class ServiceAspect {

	private Logger logger = LoggerFactory.getLogger(ServiceAspect.class);
	
	@Pointcut("execution(* com.sinosoft.ptas.service.*.update*(..))")
	public void pointCut_update() {}
	
	@Pointcut("execution(* com.sinosoft.ptas.service.*.create*(..))")
	public void pointCut_add() {}
	/**
	 * 增加类方法拦截处理
	 * 被拦截的service方法的第一个参数必须是持久化实体类或实体类集合
	 * @param jp	切点
	 */
	@SuppressWarnings("unchecked")
	@Before("pointCut_update() {}")
	public void beforeUpdate(JoinPoint jp){
		logger.info("开始执行切面方法[beforeUpdate]拦截处理:" + jp.getSourceLocation());
		//String username = SecurityUtil.getUsername(); 
		//SecurityUtils.getSubject().getSession().getAttribute("userName");	//	获取当前会话的用户帐号
		Object arg = jp.getArgs()[0];	//	获取增加类方法的参数
		boolean isExistUpdater = isExistFiled(arg.getClass(),"updater");
		boolean isExistUpdaterdate = isExistFiled(arg.getClass(),"updateTime");
		if(isExistUpdater && isExistUpdaterdate){
			if(arg instanceof List){
				List<Object> args = (List<Object>) arg;
				for(int i=0; i<args.size(); i++) {
						invokeMethod(args.get(i), "setUpdater", String.class, "admin");	//	调用设置创建者函数给其赋值
						invokeMethod(args.get(i), "setUpdateTime", Date.class, new Date());	//	调用设置创建日期函数给其赋值
				}								   
			}else{
					invokeMethod(arg, "setUpdater", String.class, "admin");	//	调用设置创建者函数给其赋值
					invokeMethod(arg, "setUpdateTime", Date.class, new Date());	//	调用设置创建日期函数给其赋值
			}						   
		}else{
			String className = arg.getClass().getName();
			logger.info(className+"类没有updater和updateTime属性");
		}
	}
	
	/**
	 * 更新类方法拦截处理
	 * @param jp	切点
	 */
	@SuppressWarnings("unchecked")
	@Before("pointCut_add() {}")
	public void beforeAdd(JoinPoint jp) {
		logger.info("开始执行切面方法[beforeAdd]拦截处理:beforeAdd" + jp.getSourceLocation());
		//String username = SecurityUtil.getUsername();	//	获取当前会话的用户帐号
		Object arg = jp.getArgs()[0];
		boolean isExistUpdater = isExistFiled(arg.getClass(),"creater");
		boolean isExistUpdaterdate = isExistFiled(arg.getClass(),"createTime");
		/*切List*/
		if(arg instanceof List){
			List<Object> argslist = (List<Object>) arg;
			for(int i=0; i<argslist.size(); i++) {
				 isExistUpdater = isExistFiled( argslist.get(i).getClass(),"creater");
				 isExistUpdaterdate = isExistFiled(argslist.get(i).getClass(),"createTime");
				if(isExistUpdater && isExistUpdaterdate){
					invokeMethod(argslist.get(i), "setCreater", String.class, "admin");	//	调用设置创建者函数给其赋值
					invokeMethod(argslist.get(i), "setCreateTime", Date.class, new Date());	//	调用设置创建日期函数给其赋值
				}
			}
		}
		/*切实体*/
		if(isExistUpdater && isExistUpdaterdate){
			if(arg instanceof List){
				List<Object> args = (List<Object>) arg;
				for(int i=0; i<args.size(); i++) {
					invokeMethod(args.get(i), "setCreater", String.class, "admin");	//	调用设置创建者函数给其赋值
					invokeMethod(args.get(i), "setCreateTime", Date.class, new Date());	//	调用设置创建日期函数给其赋值
				}
			}else{
				invokeMethod(arg, "setCreater", String.class, "admin");	//	调用设置创建者函数给其赋值
				invokeMethod(arg, "setCreateTime", Date.class, new Date());	//	调用设置创建日期函数给其赋值
			}
		}else{
			String className = arg.getClass().getName();
			logger.info(className+"类没有creater和createTime属性");
		}
	}
	
	/**
	 * 反射调用方法
	 * @param object	拥有方法的对象实例
	 * @param methodName	方法名称
	 * @param argsType	参数类型
	 * @param args	方法参数
	 */
	private void invokeMethod(Object object, String methodName, Class<?> argsType, Object... args){
		Method method = null;
		if(object.getClass()!=null&&object.getClass()!=String.class){
			try {
				method = object.getClass().getMethod(methodName, argsType);
			} catch (NoSuchMethodException | SecurityException e) {
				e.printStackTrace();
			}
			try {
				method.invoke(object, args);
			} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 判断实体类中是否具有某个字段
	 * @param argsType 实体类型
	 * @param fieldName 字段名称
	 * @return false/true
	 */
	private boolean isExistFiled(Class<?> argsType,String fieldName){
		Field[] fields=argsType.getDeclaredFields();
		boolean result = false;
		for (int i = 0; i < fields.length; i++) {
			if(fields[i].getName().equals(fieldName)){
				result = true;
				break;
			}
		}
		return result;
	}
}
